﻿#include "guild_red_envelope_logic.h"

#include <unordered_map>

#include "guildservicewelfare.enum.h"
#include "GuildRedEnvelopeGrabber_struct.h"
#include "GuildRedEnvelopeBrief_struct.h"
#include "GuildRedEnvelope_struct.h"
#include "GuildModuleRedEnvelope_struct.h"


#include "error/make_error_code.h"
#include "fwd.h"
#include "guild/guild_dump.hpp"
#include "guild/module/guild_module.h"
#include "guild/module/guild_module_loader.hpp"
#include "redis/service_redis_fwd.hpp"
#include "guild/guild_loader.hpp"
#include "guild/module/guild_module_saver.hpp"

#include "util/time_util.hh"

#include "guild/guild_loader.hpp"
#include "token/service_token_mgr.hpp"

namespace guild_service {

bool GuildModuleRedEnvelopeLogic::GetModuleRedEnvelope(
    const guild_id_type guild_id, GuildModuleRedEnvelope &module_red_envelope) {
  return detail::GetGuildModule<GuildModuleRedEnvelope>(
      kGuildServiceWelfareName, guild_id, kGuildModuleRedEnvelopeName,
      module_red_envelope);
}

bool GuildModuleRedEnvelopeLogic::SendGuildRedEnvelope(
    const role_uuid_type role_uuid,
    const GuildRedEnvelopeBrief &red_envelope_brief, const std::string &passwd,
    red_envelope_uid_type &red_envelope_uid, error_code &ec) {
      // const GuildRedEnvelopeBrief red_envelope_brief -> core dump
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  if (red_envelope_brief.count == 0) {
    ec = ErrorCode::ERR_GUILD_MOD_RED_ENVELOPE_INVALID_COUNT;
    return false;
  }
  
  guild_id_type guild_id = kInvalidGuildId;
  if (!detail::LoadGuildIdByRole(kGuildServiceWelfareName, role_uuid, guild_id)) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleRedEnvelope module_red_envelope;
  if (!GuildModuleRedEnvelopeLogic::GetModuleRedEnvelope(guild_id, module_red_envelope)) {
    ec = ErrorCode::ERR_GUILD_MOD_RED_ENVELOPE_LOAD_FAILED;
    return false;
  }

  time_t now_time = kratos::util::get_os_time_millionsecond();

  GuildRedEnvelope red_envelope;
  red_envelope.brief = red_envelope_brief;
  red_envelope.brief.sender_role_uuid = role_uuid;
  red_envelope.send_timestamp = now_time;
  red_envelope.expired_timestamp = now_time + 10 * 1000;
  red_envelope.passwd = passwd;
  {// 生成uuid
    uint32_t red_envelope_id = ++module_red_envelope.red_envelope_id;
    // 16位公会id | 16位时间戳 | 32位自增id
    red_envelope.uid = ((0xffff000000000000 & (guild_id << 48))) |
                        (0x0000ffff00000000 & (now_time << 32)) | red_envelope_id;
    
    red_envelope_uid = red_envelope.uid;
  }

  if (!module_red_envelope.red_envelope_map
           .emplace(red_envelope.uid, red_envelope)
           .second) {
    ec = ErrorCode::ERR_GUILD_MOD_RED_ENVELOPE_ADD_FAILED;
    return false;
  }
  
  if (!detail::SaveGuildModule<GuildModuleRedEnvelope>(
      kGuildServiceWelfareName, module_red_envelope, guild_id,
          kGuildModuleRedEnvelopeName)) {
    ec = ErrorCode::ERR_GUILD_MOD_RED_ENVELOPE_SAVE_FAILED;
  }

  return true;
}

bool GuildModuleRedEnvelopeLogic::GrabGuildRedEnvelope(
    const role_uuid_type role_uuid,
    const red_envelope_uid_type red_envelope_uid,
    GuildRedEnvelopeBrief &red_envelope_brief,
    std::vector<GuildRedEnvelopeGrabber> &grabber_list, error_code &ec) {
  grabber_list.clear();
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  guild_id_type guild_id = kInvalidGuildId;
  if (!detail::LoadGuildIdByRole(kGuildServiceWelfareName, role_uuid,
                                 guild_id)) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleRedEnvelope module_red_envelope;
  if (!GuildModuleRedEnvelopeLogic::GetModuleRedEnvelope(guild_id,
                                                         module_red_envelope)) {
    ec = ErrorCode::ERR_GUILD_MOD_RED_ENVELOPE_LOAD_FAILED;
    return false;
  }

  {
    auto &red_envelope_map = module_red_envelope.red_envelope_map;
    auto it = red_envelope_map.find(red_envelope_uid);
    if (it == red_envelope_map.end()) {
      ec = ErrorCode::ERR_GUILD_MOD_RED_ENVELOPE_NOT_EXIST;
      return false;
    }
    GuildRedEnvelopeGrabber grabber;
    grabber.role_uuid = role_uuid;
    grabber.grab_timestamp = kratos::util::get_os_time_millionsecond();
    grabber.money = 1.0 * it->second.brief.money / it->second.brief.count;

    it->second.grabber_list.emplace_back(grabber);

    red_envelope_brief = it->second.brief;
    grabber_list = it->second.grabber_list;
  }

  if (!detail::SaveGuildModule<GuildModuleRedEnvelope>(
          kGuildServiceWelfareName, module_red_envelope, guild_id,
          kGuildModuleRedEnvelopeName)) {
    ec = ErrorCode::ERR_GUILD_MOD_RED_ENVELOPE_SAVE_FAILED;
    return false;
  }

  return true;
}



}  // namespace guild_service
